package com.blockchain.securewallet.activities;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Vibrator;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.blockchain.securewallet.R;
import com.blockchain.securewallet.WalletApp;
import com.blockchain.securewallet.base.BaseActivity;
import com.blockchain.securewallet.interfaces.WalletFields;
import com.blockchain.securewallet.model.db.Account;
import com.blockchain.securewallet.model.db.CoinWallet;
import com.blockchain.securewallet.model.db.UnSpent;
import com.blockchain.securewallet.model.db.oper.AccountDaoOpe;
import com.blockchain.securewallet.model.db.oper.UnSpentDaoOpe;
import com.blockchain.securewallet.tools.ActivityLauncher;
import com.blockchain.securewallet.tools.LZW;
import com.blockchain.securewallet.utils.AddressValidity;
import com.blockchain.securewallet.utils.Logger;
import com.blockchain.securewallet.utils.ToastUtils;
import com.blockchain.securewallet.utils.UIHelper;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import cn.bingoogolapple.qrcode.core.QRCodeView;
import pub.devrel.easypermissions.EasyPermissions;

public class QrCodeScanActivity extends BaseActivity
        implements QRCodeView.Delegate, EasyPermissions.PermissionCallbacks, View.OnClickListener {

    private static final String TAG = "Wallet.QrCodeScan";

    public static final String KEY_MODULE_FROM = "module_from";
    public static final String KEY_WALLET_ID = "wallet_id";
    public static final int MODULE_ADD_ADDRESS = 0;
    public static final int MODULE_UPDATE_WALLET = 1;
    public static final int MODULE_SEND_COIN = 2;
    public static final int MODULE_RESTORE_SEED = 3;
    public static final int MODULE_UPDATE_ERROE = 4;

    @BindView(R.id.qr_code_scan_view)
    QRCodeView mQrCodeScanView;

    @BindView(R.id.btn_back)
    ImageButton btnBack;

    @BindView(R.id.tv_title)
    TextView tvTitle;

    @BindView(R.id.tv_tips_scan)
    TextView tv_tips_scan;

    @BindView(R.id.tv_tips_next)
    TextView tv_tips_next;

    @BindView(R.id.rl_how_to_update)
    RelativeLayout rl_how_to_update;

    @BindView(R.id.rl_tips_help_balance)
    RelativeLayout rl_tips_help_balance;

    //从哪个模块来
    private int moduleFrom = 0;
    private int walletId = -1;
    private CoinWallet wallet = null;

    //二维码当前页数？
    private int pos = -1;
    private int type = -1;
    private String chinaType;

    private int total;
    HashMap<Integer, String> infoMap = new LinkedHashMap<>();
    //当前已经扫描的张数
    private int count = 0;
    private String realAddress;
    private Pattern pattern;
    private Matcher matcher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_qr_code_scan);
        ButterKnife.bind(this);
        Intent intent = getIntent();
        if (intent != null) {
            walletId = intent.getIntExtra(KEY_WALLET_ID, -1);
            moduleFrom = intent.getIntExtra(KEY_MODULE_FROM, MODULE_ADD_ADDRESS);

            //待修改
            if (walletId != -1) {
                wallet = WalletApp.getInstance().queryCurrrentWallet().get(walletId);
//                wallet = WalletApp.getInstance().getDaoSession().load(CoinWallet.class, walletId);
            }

            pos = intent.getIntExtra(SendCoinActivity.KEY_POS, -1);
            type = intent.getIntExtra(SendCoinActivity.KEY_TYPE_COIN, -1);
            if (type == CoinWallet.TYPE_BIT_COIN) {
                chinaType = "比特币";
            } else {
                chinaType = "以太坊";
            }
        }

        tvTitle.setText(R.string.scan);
        tvTitle.setTextSize(15f);

        //余额更新提示设置
        initBalanceShow();

        mQrCodeScanView.setDelegate(this);
    }


    @Override
    protected void onStart() {
        super.onStart();
        mQrCodeScanView.startCamera();
        mQrCodeScanView.showScanRect();
    }

    @Override
    protected void onStop() {
        mQrCodeScanView.stopCamera();
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        mQrCodeScanView.onDestroy();
        super.onDestroy();
    }

    @Override
    protected void onResume() {
        super.onResume();

        //请求权限
        int hasWriteContactsPermission = ContextCompat.checkSelfPermission(QrCodeScanActivity.this, Manifest.permission.CAMERA);
        if (hasWriteContactsPermission == PackageManager.PERMISSION_GRANTED) {

        }//需要弹出dialog让用户手动赋予权限
        else {
            ActivityCompat.requestPermissions(QrCodeScanActivity.this, new String[]{Manifest.permission.CAMERA}, 1);
        }


        mQrCodeScanView.startSpot();
    }

    private void vibrate() {
        Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
        vibrator.vibrate(200);
    }

    @Override
    public void onScanQRCodeSuccess(String result) {
        Log.d(TAG, "QrCode Scan Result:" + result);
        vibrate();
        mQrCodeScanView.startSpot();
        Intent intent = new Intent();

        switch (moduleFrom) {
            //添加地址
            case MODULE_ADD_ADDRESS:

                //判断地址有效性并过滤
                realAddress = filterAddressAndValidity(result);
                if (realAddress != null) {
                    intent.putExtra(AddressAddActivity.KEY_ADDRESS, realAddress);
                    setResult(0, intent);
                    finish();
                } else {
                    ToastUtils.showToast("扫描的信息不匹配" + chinaType + "地址");
                }

                break;
            case MODULE_SEND_COIN:
                if (type != -1 && pos != -1) {
                    //判断地址有效性并过滤
                    realAddress = filterAddressAndValidity(result);
                    if (realAddress != null) {
                        intent.putExtra(SendCoinActivity.KEY_ADDRESS, realAddress);
                        intent.putExtra(SendCoinActivity.KEY_POS, pos);
                        setResult(0, intent);
                        finish();
                    } else {
                        ToastUtils.showToast("扫描的信息不匹配" + chinaType + "地址");
                    }

                }
                break;
            case MODULE_RESTORE_SEED:
                intent.putExtra(SeedWordsInputActivity.KEY_WORDS_LIST, result);
                intent.setClass(this, SeedWordsInputActivity.class);
                startActivity(intent);
                finish();
                break;
            default:
                if (wallet != null) {
                    handleWalletInfoResult(result);
                }
                break;
        }

    }

    private String filterAddressAndValidity(String result) {
        String matchResult = null;
        switch (type) {
            case CoinWallet.TYPE_BIT_COIN:


                pattern = Pattern.compile("[1,3,b][0-9a-zA-Z]{32,}");
                matcher = pattern.matcher(result);
                if (matcher.find()) {
                    matchResult = matcher.group(0);
                    if (!AddressValidity.btcAddressValidity(matchResult)) {
                        matchResult = null;
                    }
                } else {
                    matchResult = null;
                }
                break;

            case CoinWallet.TYPE_ETH_COIN:

                pattern = Pattern.compile("0[xX][0-9a-fA-F]{30,}");
                matcher = pattern.matcher(result);
                if (matcher.find()) {
                    matchResult = matcher.group(0);
                } else {
                    matchResult = null;
                }


                break;

            case CoinWallet.TYPE_LTC_COIN:

                matchResult = result;

                break;

            case CoinWallet.TYPE_BCH_COIN:

                matchResult = result;

                break;

            case CoinWallet.TYPE_EOS_COIN:

                matchResult = result;

                break;


            default:
                break;

        }

        return matchResult;
    }

    @Override
    public void onScanQRCodeOpenCameraError() {
        Log.d(TAG, "open camera error");
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
//
//        if (requestCode == 1){
//            Log.i("write","cccc");
//            if (permissions[0].equals(Manifest.permission.CAMERA)
//                    &&grantResults[0] == PackageManager.PERMISSION_GRANTED){
//                //用户同意使用write
//                Log.i("write","dddd");
//                if (sdHandler!=null){
//                    Log.i("write","write");
//                    sdHandler.sendEmptyMessage(0x11);
//                }
//            }else{
//                //用户不同意，自行处理即可
////                finish();
////                ShowToast("请为该应用开启打开摄像头权限");
//            }
//        }


    }

    @Override
    public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {

    }

    @Override
    public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {

    }

    @OnClick(R.id.btn_back)
    void back() {
        finish();
    }

    private boolean handleWalletInfoResult(String result) {
        try {
            JSONObject root = new JSONObject(result);
            //n表示总页数
            int n = root.optInt("n");
            if (n == 0) n = 1;

            if (total != n) {
                total = n;
                count = 0;
                infoMap.clear();
            }

            //当前是第几张二维码
            int i = root.optInt("i");
            //元数据
            String d = root.getString("d");

            if (TextUtils.isEmpty(infoMap.get(i))) {
                infoMap.put(i, d);
                ++count;
            }
            if (count == total) {
                ToastUtils.showToast("余额更新完成");
                new AsyncTask<Void, Void, Boolean>() {
                    @Override
                    protected Boolean doInBackground(Void... voids) {
                        StringBuilder builder = new StringBuilder();
                        for (int i = 0; i < total; ++i) {
                            builder.append(infoMap.get(i));
                        }

                        String metadata = builder.toString();
                        //byte[] decode = Base64.decode(metadata, 0);
                        //现在使用LZW进行替换
                        //String decodeText = new String(decode);

                        //解密后的元数据（"d"）
                        String decrypt = LZW.decrypt(metadata);
                        Logger.ds("all metadata:" + metadata);
                        Logger.ds("元数据 decrypt:" + decrypt);
                        Log.i("datada",decrypt);
                        //Logger.ds("all decode:" + decodeText);

                        if (wallet.getType() == CoinWallet.TYPE_BIT_COIN) {
                            return parseBitCoinEncodeData(decrypt);
                        } else if (wallet.getType() == CoinWallet.TYPE_ETH_COIN) {
                            return parseEtherEncodeData(decrypt);
                        } else if (wallet.getType() == CoinWallet.TYPE_LTC_COIN) {
                            return parseLtcCoinEncodeData(decrypt);
                        } else if (wallet.getType() == CoinWallet.TYPE_BCH_COIN) {
                            return parseBchCoinEncodeData(decrypt);
                        } else {
                            ToastUtils.showToast("Other：币种待添加！");
                            return false;
                        }
                    }

                    @Override
                    protected void onPostExecute(Boolean success) {
                        if (success) {
                            Account account = WalletApp.getInstance().queryCurrrentAccount();
                            if (account != null) {
                                account.getCoinWalletList().remove(walletId);
                                account.getCoinWalletList().add(walletId, wallet);
                                AccountDaoOpe.updateData(QrCodeScanActivity.this, account);
                            }
//                            Log.i("ceshixia",account.getCoinWalletList().get(0).toString());
//                            Log.i("ceshixia",AccountDaoOpe.queryAll(QrCodeScanActivity.this).get(0).getCoinWalletList().get(0).toString());
//                            Log.i("ceshixia",WalletApp.getInstance().queryCurrrentWallet().get(0).toString());
//                            Log.i("ceshixia",account.getCoinWalletList().get(1).toString());

                        } else {
                            ToastUtils.showToast("信息更新失败");
                        }

//                            WalletApp.getInstance().getDaoSession().getCoinWalletDao().update(wallet);
                        finish();
                    }
                }.execute();

            } else {
                int priviewCount = count + 1;
                ToastUtils.showToast("请扫描第" + priviewCount + "张");
            }
        } catch (JSONException e) {
            return false;
        }
        return true;
    }

    private Boolean parseBchCoinEncodeData(String decodeText) {
        try {
            JSONObject root = new JSONObject(decodeText);
            String address = root.optString("a");
            int type = root.optInt("t");
            if (!address.equals(wallet.getAddress()) || type != wallet.getType()) {
                addressWrong();
                return false;
            }
            long fee = root.optLong("f");
            if (fee != 0L) {
                Logger.ds("网上更新过来的bch手续费: " + fee);
                WalletApp.getInstance().saveBchCoinFee(fee*1000);
            }
            JSONArray jsonUtxo = root.getJSONArray("d");
            long value = 0L;
            List<UnSpent> unSpents = new ArrayList<>();
            for (int i = 0; i < jsonUtxo.length(); ++i) {
                JSONObject item = jsonUtxo.getJSONObject(i);
                UnSpent u = new UnSpent();
                u.setOutputNo(item.getInt("n"));
                u.setTxid(item.getString("h"));
                u.setScript(item.getString("s"));
                u.setValue(item.getLong("v"));
                u.setAddress(address);
                unSpents.add(u);
                value += item.getLong("v");
            }
            wallet.setValue(value);
            UnSpentDaoOpe.deleteDataFromAddress(this, address);
            UnSpentDaoOpe.insertData(this, unSpents);
        } catch (Exception e) {
            Log.i("ywLog", "allTextgetMessage:" + e.getMessage());
            return false;
        }
        return true;
    }

    private boolean parseLtcCoinEncodeData(String decodeText) {
        try {
            JSONObject root = new JSONObject(decodeText);
            String address = root.optString("a");
            int type = root.optInt("t");
            if (!address.equals(wallet.getAddress()) || type != wallet.getType()) {
                addressWrong();
                return false;
            }
            long fee = root.optLong("f");
            if (fee != 0L) {
                Logger.ds("网上更新过来的ltc手续费: " + fee);
                WalletApp.getInstance().saveLtcCoinFee(fee*1000);
            }
            JSONArray jsonUtxo = root.getJSONArray("d");
            long value = 0L;
            List<UnSpent> unSpents = new ArrayList<>();
            for (int i = 0; i < jsonUtxo.length(); ++i) {
                JSONObject item = jsonUtxo.getJSONObject(i);
                UnSpent u = new UnSpent();
                u.setOutputNo(item.getInt("n"));
                u.setTxid(item.getString("h"));
                u.setScript(item.getString("s"));
                u.setValue(item.getLong("v"));
                u.setAddress(address);
                unSpents.add(u);
                value += item.getLong("v");
            }
            wallet.setValue(value);
            UnSpentDaoOpe.deleteDataFromAddress(this, address);
            UnSpentDaoOpe.insertData(this, unSpents);
        } catch (Exception e) {
            Log.i("ywLog", "allTextgetMessage:" + e.getMessage());
            return false;
        }
        return true;
    }



    private boolean parseBitCoinEncodeData(String decodeText) {
        try {
            JSONObject root = new JSONObject(decodeText);
            String address = root.optString("a");
            int type = root.optInt("t");
            if (!address.equals(wallet.getAddress()) || type != wallet.getType()) {
                addressWrong();
                return false;
            }
            long fee = root.optLong("f");
            if (fee != 0L) {
                Logger.ds("网上更新过来的btc手续费: " + fee);
                WalletApp.getInstance().saveBitCoinFee(fee);
            }
            JSONArray jsonUtxo = root.getJSONArray("d");
            long value = 0L;
            List<UnSpent> unSpents = new ArrayList<>();
            for (int i = 0; i < jsonUtxo.length(); ++i) {
                JSONObject item = jsonUtxo.getJSONObject(i);
                UnSpent u = new UnSpent();
                u.setOutputNo(item.getInt("n"));
                u.setTxid(item.getString("h"));
                u.setScript(item.getString("s"));
                u.setValue(item.getLong("v"));
                u.setAddress(address);
                unSpents.add(u);
                value += item.getLong("v");
            }
            wallet.setValue(value);
            UnSpentDaoOpe.deleteDataFromAddress(this, address);
            UnSpentDaoOpe.insertData(this, unSpents);
        } catch (Exception e) {
            Log.i("ywLog", "allTextgetMessage:" + e.getMessage());
            return false;
        }
        return true;
    }

    private boolean parseEtherEncodeData(String decodeText) {
        try {
            JSONObject root = new JSONObject(decodeText);
            String address = root.getString("a");
            int type = root.getInt("t");
            if (!address.equals(wallet.getAddress()) || type != wallet.getType()) {
                addressWrong();
                return false;
            }
            root = root.getJSONObject("d");
            long value = root.optLong("p");
            if (value > 0L) {
                WalletApp.getInstance().saveGasPrice(value);
            }
            value = root.optLong("l");// lower case of L
            if (value > 0L) {
                WalletApp.getInstance().saveGasLimit(value);
            }
            value = root.optLong("n");
            if (value > 0L) {
                WalletApp.getInstance().saveNonce(value);
            }
            long balance = root.optLong("v");
//            value = root.optLong("v");
            if (balance > 0) {
                wallet.setValue(balance);
//                WalletApp.getInstance().getDaoSession().getCoinWalletDao().update(wallet);
            }
        } catch (JSONException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    private void addressWrong() {
        Intent intent = new Intent();
        intent.setClass(this, QueryAccountQrCodeActivity.class);
        intent.putExtra(QueryAccountQrCodeActivity.KEY_MODULE_FROM, QueryAccountQrCodeActivity.MODULE_SCAN);
        intent.putExtra(QueryAccountQrCodeActivity.KEY_WALLET_ID, wallet.getId());
        startActivity(intent);
        finish();
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.rl_how_to_update:
                //ToastUtils.showToast("前往FAQ");
                //ActivityLauncher.gotoFAQActivity(this);
                ActivityLauncher.gotoFAQDetailsActivity(this, WalletFields.FAQ.BALANCE_UPDATE);
                break;
            case R.id.rl_tips_help_balance:
                //ToastUtils.showToast("前往余额更新界面");
                updateByAddress();
                break;
        }
    }

    void updateByAddress() {
        Intent intent = new Intent();
        intent.setClass(this, QueryAccountQrCodeActivity.class);
        intent.putExtra(QueryAccountQrCodeActivity.KEY_MODULE_FROM, QueryAccountQrCodeActivity.MODULE_WALLET);
        intent.putExtra(QueryAccountQrCodeActivity.KEY_WALLET_ID, wallet.getId());
        startActivity(intent);
    }


    //根据扫描类型设置是否显示余额更新提示
    private void initBalanceShow() {
        if (moduleFrom == MODULE_UPDATE_WALLET) {
            tv_tips_scan.setVisibility(View.VISIBLE);
            rl_how_to_update.setVisibility(View.VISIBLE);
            rl_tips_help_balance.setVisibility(View.VISIBLE);

            //TextView tv1 = (TextView) rl_tips_help_balance.getChildAt(0);
            TextView tv2 = (TextView) rl_tips_help_balance.getChildAt(1);

            String content = getResources().getString(R.string.tips_help_balance_update2);
            UIHelper.initHighLight(this, content, content, tv2, R.color.scan_tips_highlight, true);

            UIHelper.expandViewTouchDelegate(rl_how_to_update, 60, 60, 60, 60);

            rl_how_to_update.setOnClickListener(this);
            rl_tips_help_balance.setOnClickListener(this);

        } else if (moduleFrom == MODULE_UPDATE_ERROE) {
            tv_tips_next.setVisibility(View.VISIBLE);
        }
    }


}
